package org.springblade.thingsphere.manage.service.impl;

import cn.hutool.cache.Cache;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.api.R;
import org.springblade.thingsphere.manage.excel.ComponentsExcel;
import org.springblade.thingsphere.manage.mapper.ComponentsMapper;
import org.springblade.thingsphere.manage.pojo.entity.ComponentsEntity;
import org.springblade.thingsphere.manage.pojo.vo.ComponentsVO;
import org.springblade.thingsphere.manage.service.IComponentsService;
import org.springblade.thingsphere.network.components.NetworkType;
import org.springblade.thingsphere.network.components.common.HttpServerConfig;
import org.springblade.thingsphere.network.components.common.MqttClientConfig;
import org.springblade.thingsphere.network.components.common.MqttServerConfig;
import org.springblade.thingsphere.network.components.http.server.VertxHttpServer;
import org.springblade.thingsphere.network.components.mqtt.client.VertxMqttClient;
import org.springblade.thingsphere.network.components.mqtt.server.VertxMqttServer;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 网络组件 服务实现类
 *
 * @author lhb
 * @since 2024-09-27
 */
@Slf4j
@Service
@AllArgsConstructor
public class ComponentsServiceImpl extends BaseServiceImpl<ComponentsMapper, ComponentsEntity> implements IComponentsService {

	private final VertxHttpServer vertxHttpServer;
	private final VertxMqttServer vertxMqttServer;
	private final VertxMqttClient vertxMqttClient;

	private static final String CACHE_NAME = "iot:components";

	@Override
	public IPage<ComponentsVO> selectComponentsPage(IPage<ComponentsVO> page, ComponentsVO components) {
		return page.setRecords(baseMapper.selectComponentsPage(page, components));
	}


	@Override
	public List<ComponentsExcel> exportComponents(Wrapper<ComponentsEntity> queryWrapper) {
		List<ComponentsExcel> componentsList = baseMapper.exportComponents(queryWrapper);
		//componentsList.forEach(components -> {
		//	components.setTypeName(DictCache.getValue(DictEnum.YES_NO, Components.getType()));
		//});
		return componentsList;
	}

	@Override
	public R<Boolean> start(ComponentsVO componentsVO) {
		// 根据类型启动组件监听
		ComponentsEntity components = this.getById(componentsVO.getId());
		if (1 == components.getStatus()) {
			throw new ServiceException("网络组件已启动");
		}
		if (NetworkType.HTTP_SERVER.getName().equals(components.getType())) {
			HttpServerConfig httpServerConfig = JSONObject.parseObject(components.getConfiguration(), HttpServerConfig.class);
			httpServerConfig.setId(components.getId());
			vertxHttpServer.createNetwork(httpServerConfig);
		} else if (NetworkType.MQTT_SERVER.getName().equals(components.getType())) {
			MqttServerConfig httpServerConfig = JSONObject.parseObject(components.getConfiguration(), MqttServerConfig.class);
			httpServerConfig.setId(components.getId());
			vertxMqttServer.createNetwork(httpServerConfig);
		} else if (NetworkType.MQTT_CLIENT.getName().equals(components.getType())) {
			MqttClientConfig httpClientConfig = JSONObject.parseObject(components.getConfiguration(), MqttClientConfig.class);
			httpClientConfig.setId(components.getId());
			vertxMqttClient.createNetwork(httpClientConfig);
		}
		log.info("Listening port succeeded:{}", components);
		// 修改网络组件状态
		components.setStatus(1);
		return R.status(this.updateById(components));
	}

	@Override
	public R<Boolean> stop(ComponentsVO componentsVO) {
		ComponentsEntity components = this.getById(componentsVO.getId());
		// 停用组件监听
		if (NetworkType.HTTP_SERVER.getName().equals(components.getType())) {
			vertxHttpServer.shutdown(components.getId());
		} else if (NetworkType.MQTT_SERVER.getName().equals(components.getType())) {
			vertxMqttServer.shutdown(components.getId());
		} else if (NetworkType.MQTT_CLIENT.getName().equals(components.getType())) {
			vertxMqttClient.shutdown(components.getId());
		}
		// 修改状态
		components.setStatus(0);
		return R.status(this.updateById(components));
	}

	private static final Cache<String, List<ComponentsEntity>> fifoCache = cn.hutool.cache.CacheUtil.newFIFOCache(1000);

	@Override
	public boolean dictClear() {
		fifoCache.clear();
		return true;
	}

	@Override
	public List<ComponentsEntity> dictList() {
		if (fifoCache.containsKey(CACHE_NAME)) {
			return fifoCache.get(CACHE_NAME);
		}

		List<ComponentsEntity> list = this.list(Wrappers.<ComponentsEntity>lambdaQuery().eq(ComponentsEntity::getStatus, 1));
		fifoCache.put(CACHE_NAME, list);
		return list;
	}

}
